#include "slepoptionswidget.h"

SlepOptionsWidget::SlepOptionsWidget()
{
    QVBoxLayout *layout = new QVBoxLayout;
    tabWidget = new QTabWidget;
    opts = (OPTS*) malloc(sizeof(OPTS));
    memset(opts,0,sizeof(opts));
    setLayout(layout);
    layout->addWidget(tabWidget);
    createStartOptions();
    createTerminationOptions();
    createNormalizationOptions();
    createReguarizationParameterOptions();
    createMethodFlags();
    createButtons();
	connect(buttonOk, SIGNAL(clicked()), this, SLOT(accepted()));
	connect(buttonOk, SIGNAL(clicked()), this, SLOT(notAccepted()));

}

void SlepOptionsWidget::createSlepOptionsWidget(SLEP_METHOD method){
}


void SlepOptionsWidget::createTerminationOptions(){
    QLayout *layout = new QVBoxLayout(this);
    QWidget *terminationOptionsWidget = new QWidget(this);
    terminationOptionsWidget->setLayout(layout);

    tabWidget->addTab(terminationOptionsWidget,tr("Termination"));

    terminationOptions = new QGroupBox(tr("Termination Options"),this);
    QGridLayout *gterminationLayout = new QGridLayout;
    labelMaxIter = new QLabel(tr("Maximum Iterations"),this);
    spinBoxMaxIter = new QSpinBox(this);
    spinBoxMaxIter->setRange(1,1000000);
    spinBoxMaxIter->setSingleStep(10);
    spinBoxMaxIter->setValue(1000);
    labelMaxIter->setBuddy(spinBoxMaxIter);
    gterminationLayout->addWidget(labelMaxIter,0,0,Qt::AlignLeft);
    gterminationLayout->addWidget(spinBoxMaxIter,0,1,Qt::AlignCenter);
    connect(spinBoxMaxIter,SIGNAL(valueChanged(int)),this, SLOT(setOPTS_maxIter(int)));
    opts->maxIter=1000;


    labelTolerance = new QLabel(tr("Tolerance"),this);
    dspinBoxTolerance = new QDoubleSpinBox(this);
    dspinBoxTolerance->setDecimals(6);
    dspinBoxTolerance->setRange(0.000001,1.0);
    dspinBoxTolerance->setSingleStep(0.00001);
    dspinBoxTolerance->setValue(0.0001);
    labelTolerance->setBuddy(dspinBoxTolerance);
    gterminationLayout->addWidget(labelTolerance,1,0,Qt::AlignLeft);
    gterminationLayout->addWidget(dspinBoxTolerance,1,1,Qt::AlignCenter);
    connect(dspinBoxTolerance,SIGNAL(valueChanged(double)),this,SLOT(setOPTS_tol(double)));
    opts->tol = 0.0001;

    buttonGroupTFlag = new QButtonGroup(this);
    labelTFlag = new QLabel(tr("Termination condition:"),this);

    buttonGroupTFlag->addButton(new QRadioButton(tr("f - fprevious < tolerance")),0);
    buttonGroupTFlag->addButton(new QRadioButton(tr("f - fprevious < (tolerance * f)")),1);
    buttonGroupTFlag->addButton(new QRadioButton(tr("f < tolerance ")),2);
    buttonGroupTFlag->addButton(new QRadioButton(tr("|x-xprevious|_2 < tolerance ")),3); //euclidean distance between successive solutions
    buttonGroupTFlag->addButton(new QRadioButton(tr("|x-xprevious|_2 < tolerance * |x|_2")),4);
    buttonGroupTFlag->addButton(new QRadioButton(tr("Run for maximum iterations")),5);
    buttonGroupTFlag->setExclusive(true);

    (buttonGroupTFlag->button(5))->setChecked(true);
    opts->tFlag=5;
    connect(buttonGroupTFlag,SIGNAL(buttonClicked(int)),this,SLOT(setOPTS_tFlag(int)));

    labelTFlag->setBuddy(buttonGroupTFlag->button(0));

    gterminationLayout->addWidget(labelTFlag,2,0,6,1, Qt::AlignTop | Qt::AlignLeft);
    gterminationLayout->addWidget(buttonGroupTFlag->button(0),2,1,Qt::AlignLeft);
    gterminationLayout->addWidget(buttonGroupTFlag->button(1),3,1,Qt::AlignLeft);
    gterminationLayout->addWidget(buttonGroupTFlag->button(2),4,1,Qt::AlignLeft);
    gterminationLayout->addWidget(buttonGroupTFlag->button(3),5,1,Qt::AlignLeft);
    gterminationLayout->addWidget(buttonGroupTFlag->button(4),6,1,Qt::AlignLeft);
    gterminationLayout->addWidget(buttonGroupTFlag->button(5),7,1,Qt::AlignLeft);

    terminationOptions->setLayout(gterminationLayout);
    layout->addWidget(terminationOptions);
}


void SlepOptionsWidget::createStartOptions(){
    QLayout *layout = new QVBoxLayout(this);
    QWidget *startOptionsWidget = new QWidget(this);
    startOptionsWidget->setLayout(layout);

    tabWidget->addTab(startOptionsWidget,tr("Start Options"));
    startOptions = new QGroupBox(tr("Start options"), this);

    QGridLayout *gstartLayout = new QGridLayout;

    buttonGroupInit = new QButtonGroup(this);
    labelInit = new QLabel(tr("Init"));
    buttonGroupInit->addButton(new QRadioButton(tr("x0 set automatically")),0);
    buttonGroupInit->addButton(new QRadioButton(tr("x0 and other starting points specified")),1);
    buttonGroupInit->addButton(new QRadioButton(tr("x0=zeroes")),2);
    buttonGroupInit->setExclusive(true);
    (buttonGroupInit->button(2))->setChecked(true);
    opts->init = 2;
    connect(buttonGroupInit,SIGNAL(buttonClicked(int)),this,SLOT(setOPTS_init(int)));

    gstartLayout->addWidget(labelInit,0,0,3,1,Qt::AlignTop | Qt::AlignLeft);
    gstartLayout->addWidget(buttonGroupInit->button(0),0,1, Qt::AlignLeft);
    gstartLayout->addWidget(buttonGroupInit->button(1),1,1, Qt::AlignLeft);
    gstartLayout->addWidget(buttonGroupInit->button(2),2,1, Qt::AlignLeft);

    startOptions->setLayout(gstartLayout);
    layout->addWidget(startOptions);

    x0NormOption = new QGroupBox(tr("x0"), this);
    x0NormOption->setLayout(new QGridLayout);
    x0NormOption->layout()->addWidget(new QListWidget(this));
    layout->addWidget(x0NormOption);

    c0NormOption = new QGroupBox(tr("c0"), this);
    c0NormOption->setLayout(new QGridLayout);
    QDoubleSpinBox *c0SpinBox = new QDoubleSpinBox(this);
    c0SpinBox->setRange(0.0,100.0);
    c0SpinBox->setDecimals(3);
    c0SpinBox->setSingleStep(0.001);
    c0NormOption->layout()->addWidget(c0SpinBox);
    layout->addWidget(c0NormOption);


    connect(buttonGroupInit->button(1),SIGNAL(toggled(bool)),x0NormOption,SLOT(setEnabled(bool)));
    connect(buttonGroupInit->button(1),SIGNAL(toggled(bool)),c0NormOption,SLOT(setEnabled(bool)));
    x0NormOption->setEnabled(false);
    c0NormOption->setEnabled(false);

}

void SlepOptionsWidget::createNormalizationOptions(){
    QLayout *layout = new QVBoxLayout(this);
    QWidget *normalizationOptionsWidget = new QWidget(this);
    normalizationOptionsWidget->setLayout(layout);

    tabWidget->addTab(normalizationOptionsWidget,tr("Normalization"));
    normOptions = new QGroupBox(tr("Start options"), this);

    QGridLayout *normalizationLayout = new QGridLayout;
    buttonGroupNorm = new QButtonGroup(this);
    labelNorm = new QLabel(tr("Normalization"));
    buttonGroupNorm->addButton(new QRadioButton(tr("No normalization")),0);
    buttonGroupNorm->addButton(new QRadioButton(tr("Please select mu and nu")),1);
    buttonGroupNorm->addButton(new QRadioButton(tr("Please Select mu and nu")),2);
    (buttonGroupNorm->button(0))->setChecked(true);
    opts->nFlag=0;
    connect(buttonGroupNorm,SIGNAL(buttonClicked(int)),this,SLOT(setOPTS_nFlag(int)));

    normalizationLayout->addWidget(labelNorm,0,0,3,1, Qt::AlignTop | Qt::AlignLeft);
    normalizationLayout->addWidget(buttonGroupNorm->button(0), 0, 1, Qt::AlignLeft);
    normalizationLayout->addWidget(buttonGroupNorm->button(1), 1, 1, Qt::AlignLeft);
    normalizationLayout->addWidget(buttonGroupNorm->button(2), 2, 1, Qt::AlignLeft);

    normOptions->setLayout(normalizationLayout);
    layout->addWidget(normOptions);
    checkBoxMu = new QCheckBox(tr("Import mu from file"),this);
    checkBoxNu = new QCheckBox(tr("Import nu from file"),this);
    layout->addWidget(checkBoxMu);
    layout->addWidget(new QListWidget);
    layout->addWidget(checkBoxNu);
    layout->addWidget(new QListWidget);

}


void SlepOptionsWidget::createReguarizationParameterOptions(){
    QLayout *layout = new QVBoxLayout(this);
    QWidget *regularizationOptionsWidget = new QWidget(this);
    regularizationOptionsWidget->setLayout(layout);
    tabWidget->addTab(regularizationOptionsWidget,tr("Regularization"));
    regularizationOptions = new QGroupBox(tr("Regularization parameters"), this);

    QGridLayout *regularizationLayout = new QGridLayout;
    buttonGroupRFlag = new QButtonGroup(this);
    labelRFlag = new QLabel(tr("Regularization flag"), this);
    buttonGroupRFlag->addButton(new QRadioButton(tr("lambda = input value")),0);
    buttonGroupRFlag->addButton(new QRadioButton(tr("lambda = lambda_max * lambda")),1);
    (buttonGroupRFlag->button(0))->setChecked(true);
    opts->rFlag = 0;
    connect(buttonGroupRFlag, SIGNAL(buttonClicked(int)),this,SLOT(setOPTS_rFlag(int)));

    regularizationLayout->addWidget(labelRFlag,0,0,2,1,Qt::AlignTop|Qt::AlignLeft);
    regularizationLayout->addWidget(buttonGroupRFlag->button(0),0,1,Qt::AlignLeft);
    regularizationLayout->addWidget(buttonGroupRFlag->button(1),1,1,Qt::AlignLeft);
    regularizationOptions->setLayout(regularizationLayout);


    QDoubleSpinBox *spinBoxRsL2 = new QDoubleSpinBox(this);
    QDoubleSpinBox *spinBoxRsL1 = new QDoubleSpinBox(this);
    regularizationLayout->addWidget(new QLabel(tr("L2 Regularization parameter :"),this),2,0,Qt::AlignLeft);
    regularizationLayout->addWidget(spinBoxRsL2,2,1,Qt::AlignCenter);
    spinBoxRsL2->setRange(0.0,1.0);
    spinBoxRsL2->setSingleStep(0.001);
    spinBoxRsL2->setValue(0.000);
    spinBoxRsL2->setDecimals(3);
    setOPTS_rsL2(0.0);
    connect(spinBoxRsL2,SIGNAL(valueChanged(double)),this, SLOT(setOPTS_rsL2(double)));

    regularizationLayout->addWidget(new QLabel(tr("L1 Regularization parameter :"),this),3,0,Qt::AlignLeft);
    regularizationLayout->addWidget(spinBoxRsL1,3,1,Qt::AlignCenter);
    spinBoxRsL1->setRange(0.0,1.0);
    spinBoxRsL1->setSingleStep(0.001);
    spinBoxRsL1->setValue(0.2);
    spinBoxRsL1->setDecimals(3);

    layout->addWidget(regularizationOptions);
}

void SlepOptionsWidget::createMethodFlags(){
    QLayout *layout = new QVBoxLayout(this);
    QWidget *methodFlagsWidget = new QWidget(this);
    methodFlagsWidget->setLayout(layout);
    tabWidget->addTab(methodFlagsWidget,tr("Method"));
    methodFlags = new QGroupBox(tr("Method Flags"), this);

    QGridLayout *methodFlagsLayout = new QGridLayout;

    buttonGroupMFlag = new QButtonGroup(this);
    labelMFlag = new QLabel(tr("Method used : "));
    buttonGroupMFlag->addButton(new QRadioButton(tr("Accelerated Method (uses Objective Function as compositive function)")),0);
    buttonGroupMFlag->addButton(new QRadioButton(tr("Reformulated Smooth Objective Function Method")),1);
    buttonGroupMFlag->setExclusive(true);
    (buttonGroupMFlag->button(0))->setChecked(true);

    methodFlagsLayout->addWidget(labelMFlag,0,0,2,1,Qt::AlignLeft | Qt::AlignTop);
    methodFlagsLayout->addWidget(buttonGroupMFlag->button(0),0,1,Qt::AlignLeft);
    methodFlagsLayout->addWidget(buttonGroupMFlag->button(1),1,1,Qt::AlignLeft);

    buttonGroupLFlag = new QButtonGroup(this);
    labelLFlag = new QLabel(tr("Line Search : "));
    buttonGroupLFlag->addButton(new QRadioButton(tr("Nemirovski's Line Search")),0);


    buttonGroupLFlag->addButton(new QRadioButton(tr("Adaptive Line Search")),1);
    buttonGroupLFlag->setExclusive(true);
    (buttonGroupLFlag->button(0))->setChecked(true);



    methodFlagsLayout->addWidget(labelLFlag,2,0,2,1,Qt::AlignLeft | Qt::AlignTop);
    methodFlagsLayout->addWidget(buttonGroupLFlag->button(0),2,1,Qt::AlignLeft);
    methodFlagsLayout->addWidget(buttonGroupLFlag->button(1),3,1,Qt::AlignLeft);
    (buttonGroupLFlag->button(1))->setEnabled(false);



    methodFlags->setLayout(methodFlagsLayout);

    connect(buttonGroupMFlag->button(0),SIGNAL(clicked()),buttonGroupLFlag->button(0),SLOT(click()));
    connect(buttonGroupMFlag->button(0),SIGNAL(clicked(bool)),buttonGroupLFlag->button(1),SLOT(setDisabled(bool)));
    connect(buttonGroupMFlag->button(1),SIGNAL(clicked(bool)),buttonGroupLFlag->button(1),SLOT(setEnabled(bool)));

    opts->mFlag = 0;
    opts->lFlag = 0;

    connect(buttonGroupMFlag,SIGNAL(buttonClicked(int)),this,SLOT(setOPTS_mFlag(int)));
    connect(buttonGroupLFlag,SIGNAL(buttonClicked(int)),this,SLOT(setOPTS_lFlag(int)));
    layout->addWidget(methodFlags);

}


void SlepOptionsWidget::createButtons(){

    QLayout *layout = this->layout();
    QHBoxLayout *hLayout = new QHBoxLayout;
    QWidget *buttonBox = new QWidget;
    buttonOk = new QPushButton(tr("Okay"),this);
    buttonCancel = new QPushButton(tr("Cancel"),this);
    hLayout->addWidget(buttonOk);
    hLayout->addWidget(buttonCancel);
    buttonBox->setLayout(hLayout);
    layout->addWidget(buttonBox);
}

void SlepOptionsWidget::accepted(){
    this->hide();
}

void SlepOptionsWidget::notAccepted(){
    this->hide();
}

void SlepOptionsWidget::setOPTS_init(int init){
    opts->init = init;
}

void SlepOptionsWidget::setOPTS_lFlag(int lFlag){
    opts->lFlag = lFlag;
}

void SlepOptionsWidget::setOPTS_mFlag(int mFlag){
    opts->mFlag = mFlag;
}

void SlepOptionsWidget::setOPTS_nFlag(int nFlag){
    opts->nFlag = nFlag;
}

void SlepOptionsWidget::setOPTS_tFlag(int tFlag){
    opts->tFlag = tFlag;
}

void SlepOptionsWidget::setOPTS_maxIter(int maxIter){
    opts->maxIter = maxIter;
}

void SlepOptionsWidget::setOPTS_tol(double tol){

    opts->REGISTER = (OPTS_REGISTRY)((opts->REGISTER) | SlepOPT_tol);
    opts->tol = tol;
}


void SlepOptionsWidget::setOPTS_rFlag(int rFlag){
    opts->rFlag = rFlag;
}


void SlepOptionsWidget::setOPTS_rsL2(double rsL2){
    if(rsL2 != 0.0){
        opts->rsL2 = rsL2;
        setREGISTER(opts,SlepOPT_rsL2);
    }else{
        opts->rsL2 = 0.0;
        unsetREGISTER(opts,SlepOPT_rsL2);
    }

}
